package main
import (
	"net"
	"../logger"
	"../packet"
)

type Buffer struct {
	ctrl    chan bool   // control to exit
	pending chan []byte // pending packet
	max     int         // max queue
	conn    net.Conn    // connection
	sess    *Session    // session

}

func (buf *Buffer) Send(data []byte) (err error) {

	defer func() {
		if p := recover(); p != nil {
			logger.WARN("buffer send faild:", p)
		}
	}()
	buf.pending <- data
	return nil
}


func (buf *Buffer) Start() {
	defer func() {
		if x := recover(); x != nil {
			logger.ERR("Caught panic in buffer goroutine", x)
		}
	}()

	for {
		select {
		case data := <-buf.pending:
			buf.raw_send(data)
		case <-buf.ctrl:
			close(buf.pending)
			for data := range buf.pending {
				buf.raw_send(data)
			}
			buf.conn.Close()
			return
		}
	}
}

func (buf *Buffer) raw_send(data []byte) {
	watter := packet.Writer()
	watter.WriteU16(uint16(len(data)))
	watter.WriteRawBytes(data)

	n, err := buf.conn.Write(watter.Data())
	if err != nil {
		logger.ERR("Err send reply, bytes:", n, "error:", err)
		return
	}
}

func NewBuffer(sess *Session, conn net.Conn, ctrl chan bool) *Buffer {
	buf := Buffer{conn : conn}
	buf.ctrl = ctrl
	buf.pending = make(chan []byte, _DEFAULT_OUTQUEUE_SIZE)
	buf.max = _DEFAULT_OUTQUEUE_SIZE;
	buf.sess = sess
	return &buf
}
